Pelajari cara mengimplementasikan React Error Boundary dengan hooks untuk menangani kesalahan pemuatan sumber daya dengan baik, meningkatkan pengalaman pengguna dan stabilitas aplikasi.
Pemuatan Sumber Daya yang Tangguh di React: Menguasai Error Boundary dengan Hooks
Dalam aplikasi web modern, memuat sumber daya secara asinkron adalah praktik yang umum. Baik itu mengambil data dari API, memuat gambar, atau mengimpor modul, menangani potensi kesalahan selama pemuatan sumber daya sangat penting untuk pengalaman pengguna yang lancar. React Error Boundary menyediakan mekanisme untuk menangkap kesalahan JavaScript di mana pun dalam pohon komponen turunannya, mencatat kesalahan tersebut, dan menampilkan UI fallback alih-alih merusak seluruh aplikasi. Artikel ini membahas cara menggunakan Error Boundary secara efektif bersama dengan React Hooks untuk mengelola kesalahan pemuatan sumber daya.
Memahami Error Boundary
Sebelum React 16, kesalahan JavaScript yang tidak tertangani selama rendering komponen akan merusak state internal React dan menyebabkan kesalahan yang tidak jelas pada render berikutnya. Error Boundary mengatasi ini dengan bertindak sebagai blok penangkap semua untuk kesalahan yang terjadi pada komponen turunannya. Mereka adalah komponen React yang mengimplementasikan salah satu atau kedua metode siklus hidup berikut:
static getDerivedStateFromError(error): Metode statis ini dipanggil setelah kesalahan dilemparkan oleh komponen turunan. Ia menerima kesalahan yang dilemparkan sebagai argumen dan mengembalikan nilai untuk memperbarui state komponen.componentDidCatch(error, info): Metode siklus hidup ini dipanggil setelah kesalahan dilemparkan oleh komponen turunan. Ia menerima kesalahan yang dilemparkan sebagai argumen, serta objek yang berisi informasi tentang komponen mana yang melemparkan kesalahan. Anda dapat menggunakannya untuk mencatat informasi kesalahan.
Penting untuk diketahui, Error Boundary hanya menangkap kesalahan pada fase rendering, dalam metode siklus hidup, dan dalam konstruktor dari seluruh pohon di bawahnya. Mereka tidak menangkap kesalahan untuk:
- Penangan event (pelajari lebih lanjut di bagian di bawah)
- Kode asinkron (misalnya, callback
setTimeoutataurequestAnimationFrame) - Server-side rendering
- Kesalahan yang dilemparkan di dalam Error Boundary itu sendiri (bukan pada turunannya)
Error Boundary dan React Hooks: Kombinasi yang Kuat
Meskipun komponen kelas secara tradisional digunakan untuk mengimplementasikan Error Boundary, React Hooks menawarkan pendekatan yang lebih ringkas dan fungsional. Kita dapat membuat hook useErrorBoundary yang dapat digunakan kembali yang merangkum logika penanganan kesalahan dan menyediakan cara yang mudah untuk membungkus komponen yang mungkin melemparkan kesalahan selama pemuatan sumber daya.
Membuat Hook useErrorBoundary Kustom
Berikut adalah contoh hook useErrorBoundary:
import { useState, useCallback } from 'react';
function useErrorBoundary() {
const [error, setError] = useState(null);
const resetError = useCallback(() => {
setError(null);
}, []);
const captureError = useCallback((e) => {
setError(e);
}, []);
const ErrorBoundary = useCallback(({ children, fallback }) => {
if (error) {
return fallback ? fallback : An error occurred: {error.message || String(error)};
}
return children;
}, [error]);
return { ErrorBoundary, captureError, error, resetError };
}
export default useErrorBoundary;
Penjelasan:
useState: Kami menggunakanuseStateuntuk mengelola state kesalahan. Ini pada awalnya mengatur kesalahan kenull.useCallback: Kami menggunakanuseCallbackuntuk melakukan memoize pada fungsiresetErrordancaptureError. Ini adalah praktik yang baik untuk mencegah render ulang yang tidak perlu jika fungsi-fungsi ini diteruskan sebagai props.- Komponen
ErrorBoundary: Ini adalah komponen fungsional yang dibuat denganuseCallbackyang mengambilchildrendan propfallbackopsional. Jika ada kesalahan dalam state, ia akan me-render komponenfallbackyang disediakan atau pesan kesalahan default. Jika tidak, ia akan me-render children. Ini bertindak sebagai Error Boundary kita. Array dependensi `[error]` memastikan komponen ini di-render ulang saat state `error` berubah. - Fungsi
captureError: Fungsi ini digunakan untuk mengatur state kesalahan. Anda akan memanggilnya di dalam bloktry...catchsaat memuat sumber daya. - Fungsi
resetError: Fungsi ini membersihkan state kesalahan, memungkinkan komponen untuk me-render ulang turunannya (berpotensi mencoba kembali pemuatan sumber daya).
Mengimplementasikan Pemuatan Sumber Daya dengan Penanganan Kesalahan
Sekarang, mari kita lihat bagaimana menggunakan hook ini untuk menangani kesalahan pemuatan sumber daya. Pertimbangkan komponen yang mengambil data pengguna dari sebuah API:
import React, { useState, useEffect } from 'react';
import useErrorBoundary from './useErrorBoundary';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const { ErrorBoundary, captureError, error, resetError } = useErrorBoundary();
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setUser(data);
} catch (e) {
captureError(e);
}
};
fetchData();
}, [userId, captureError]);
if (error) {
return (
Gagal memuat data pengguna. {user.name}
Email: {user.email}
{/* Detail pengguna lainnya */}Penjelasan:
- Kita mengimpor hook
useErrorBoundary. - Kita memanggil hook untuk mendapatkan komponen
ErrorBoundary, fungsicaptureError, stateerror, dan fungsiresetError. - Di dalam hook
useEffect, kita membungkus panggilan API dalam bloktry...catch. - Jika terjadi kesalahan selama panggilan API, kita memanggil
captureError(e)untuk mengatur state kesalahan. - Jika state
errordiatur, kita me-render komponenErrorBoundary. Kita menyediakan propfallbackkustom yang menampilkan pesan kesalahan dan tombol "Coba lagi". Mengklik tombol tersebut akan memanggilresetErroruntuk membersihkan state kesalahan, memicu render ulang dan upaya lain untuk mengambil data. - Jika tidak ada kesalahan dan data pengguna dimuat, kita me-render detail profil pengguna.
Menangani Berbagai Jenis Kesalahan Pemuatan Sumber Daya
Berbagai jenis kesalahan pemuatan sumber daya mungkin memerlukan strategi penanganan yang berbeda. Berikut adalah beberapa skenario umum dan cara mengatasinya:
Kesalahan Jaringan
Kesalahan jaringan terjadi ketika klien tidak dapat terhubung ke server (misalnya, karena gangguan jaringan atau server mati). Contoh di atas sudah menangani kesalahan jaringan dasar menggunakan `response.ok`. Anda mungkin ingin menambahkan deteksi kesalahan yang lebih canggih, misalnya:
//Di dalam fungsi fetchData
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
// Pertimbangkan untuk menambahkan penanganan kode kesalahan spesifik
if (response.status === 404) {
throw new Error("Pengguna tidak ditemukan");
} else if (response.status >= 500) {
throw new Error("Kesalahan server. Silakan coba lagi nanti.");
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
}
const data = await response.json();
setUser(data);
} catch (error) {
if (error.message === 'Failed to fetch') {
// Kemungkinan besar kesalahan jaringan
captureError(new Error('Kesalahan jaringan. Silakan periksa koneksi internet Anda.'));
} else {
captureError(error);
}
}
Dalam kasus ini, Anda dapat menampilkan pesan kepada pengguna yang menunjukkan bahwa ada masalah konektivitas jaringan dan menyarankan mereka untuk memeriksa koneksi internet mereka.
Kesalahan API
Kesalahan API terjadi ketika server mengembalikan respons kesalahan (misalnya, 400 Bad Request atau 500 Internal Server Error). Seperti yang ditunjukkan di atas, Anda dapat memeriksa `response.status` dan menangani kesalahan ini dengan tepat.
Kesalahan Parsing Data
Kesalahan parsing data terjadi ketika respons dari server tidak dalam format yang diharapkan dan tidak dapat di-parse (misalnya, JSON tidak valid). Anda dapat menangani kesalahan ini dengan membungkus panggilan response.json() dalam blok try...catch:
//Di dalam fungsi fetchData
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setUser(data);
} catch (error) {
if (error instanceof SyntaxError) {
captureError(new Error('Gagal mem-parse data dari server.'));
} else {
captureError(error);
}
}
Kesalahan Pemuatan Gambar
Untuk pemuatan gambar, Anda dapat menggunakan event handler onError pada tag <img>:
function MyImage({ src, alt }) {
const { ErrorBoundary, captureError } = useErrorBoundary();
const [imageLoaded, setImageLoaded] = useState(false);
const handleImageLoad = () => {
setImageLoaded(true);
};
const handleImageError = (e) => {
captureError(new Error(`Gagal memuat gambar: ${src}`));
};
return (
Gagal memuat gambar.